//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package data_anno_project_api_serv

import (
	"context"
	"time"

	"atomgit.com/openlinksaas/api-server/api_common"
	"atomgit.com/openlinksaas/api-server/dao"
	"atomgit.com/openlinksaas/api-server/dao/data_anno_dao"
	"atomgit.com/openlinksaas/api-server/dao/project_entry_dao"
	"atomgit.com/openlinksaas/api-server/utils"
	"atomgit.com/openlinksaas/proto-gen-go.git/data_anno_project_api"
	"atomgit.com/openlinksaas/proto-gen-go.git/project_entry_api"
	"github.com/google/uuid"
	"go.mongodb.org/mongo-driver/mongo"
)

func (apiImpl *DataAnnoProjectApiImpl) Create(ctx context.Context, req *data_anno_project_api.CreateRequest) (*data_anno_project_api.CreateResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &data_anno_project_api.CreateResponse{
			Code:   data_anno_project_api.CreateResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查权限
	projectItem, _, _, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &data_anno_project_api.CreateResponse{
			Code:   data_anno_project_api.CreateResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &data_anno_project_api.CreateResponse{
			Code:   data_anno_project_api.CreateResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	if projectItem.Closed {
		return &data_anno_project_api.CreateResponse{
			Code:   data_anno_project_api.CreateResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	annProjectId := uuid.NewString()

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = data_anno_dao.AnnoProjectDao.Insert(sessCtx, &data_anno_dao.AnnoProjectInfoDbItem{
			AnnoProjectId: annProjectId,
			ProjectId:     req.ProjectId,
			BaseInfo: data_anno_dao.BaseAnnoProjectInfoDbItem{
				Desc:   req.BaseInfo.Desc,
				Config: req.BaseInfo.Config,
			},
			ResourceCount: 0,
			AllTaskCount:  0,
			DoneTaskCount: 0,
			MemberCount:   0,
		})
		if err != nil {
			return nil, err
		}
		return &data_anno_project_api.CreateResponse{
			Code:          data_anno_project_api.CreateResponse_CODE_OK,
			AnnoProjectId: annProjectId,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*data_anno_project_api.CreateResponse), nil
}

func (apiImpl *DataAnnoProjectApiImpl) Update(ctx context.Context, req *data_anno_project_api.UpdateRequest) (*data_anno_project_api.UpdateResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &data_anno_project_api.UpdateResponse{
			Code:   data_anno_project_api.UpdateResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查权限
	projectItem, _, roleItem, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &data_anno_project_api.UpdateResponse{
			Code:   data_anno_project_api.UpdateResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
		}, nil
	} else if err == utils.ErrNoRole {
		return &data_anno_project_api.UpdateResponse{
			Code:   data_anno_project_api.UpdateResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	} else if err != nil {
		return nil, err
	}
	if projectItem.Closed {
		return &data_anno_project_api.UpdateResponse{
			Code:   data_anno_project_api.UpdateResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	//检查信息是否存在
	entryItem, err := project_entry_dao.EntryDao.Get(ctx, req.AnnoProjectId, req.ProjectId)
	if err != nil {
		return &data_anno_project_api.UpdateResponse{
			Code:   data_anno_project_api.UpdateResponse_CODE_NO_ANNO_PROJECT,
			ErrMsg: "标注项目不存在",
		}, nil
	}
	if entryItem.EntryType != uint32(project_entry_api.ENTRY_TYPE_ENTRY_TYPE_DATA_ANNO) {
		return &data_anno_project_api.UpdateResponse{
			Code:   data_anno_project_api.UpdateResponse_CODE_NO_ANNO_PROJECT,
			ErrMsg: "标注项目不存在",
		}, nil
	}

	hasUpdatePerm := api_common.CheckEntryCanUpdate(sessionItem, projectItem, roleItem, entryItem)

	if !hasUpdatePerm {
		return &data_anno_project_api.UpdateResponse{
			Code:   data_anno_project_api.UpdateResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	nowTime := time.Now().UnixNano() / 1e6

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = data_anno_dao.AnnoProjectDao.Update(sessCtx, req.ProjectId, req.AnnoProjectId,
			&data_anno_dao.BaseAnnoProjectInfoDbItem{
				Desc:   req.BaseInfo.Desc,
				Config: req.BaseInfo.Config,
			}, sessionItem.UserId, nowTime)
		if err != nil {
			return nil, err
		}
		return &data_anno_project_api.UpdateResponse{
			Code: data_anno_project_api.UpdateResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*data_anno_project_api.UpdateResponse), nil
}

func (apiImpl *DataAnnoProjectApiImpl) Get(ctx context.Context, req *data_anno_project_api.GetRequest) (*data_anno_project_api.GetResponse, error) {
	emptyItem := &data_anno_project_api.AnnoProjectInfo{
		BaseInfo: &data_anno_project_api.BaseAnnoProjectInfo{},
	}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &data_anno_project_api.GetResponse{
			Code:   data_anno_project_api.GetResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
			Info:   emptyItem,
		}, nil
	}
	//检查权限
	_, _, _, err := utils.GetProjectMemberRole(ctx, req.ProjectId, sessionItem.UserId)
	if err == utils.ErrNoProject {
		return &data_anno_project_api.GetResponse{
			Code:   data_anno_project_api.GetResponse_CODE_NO_PROJECT,
			ErrMsg: "项目不存在",
			Info:   emptyItem,
		}, nil
	} else if err == utils.ErrNoRole {
		return &data_anno_project_api.GetResponse{
			Code:   data_anno_project_api.GetResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
			Info:   emptyItem,
		}, nil
	} else if err != nil {
		return nil, err
	}

	memberItem, _ := data_anno_dao.AnnoMemberDao.Get(ctx, req.AnnoProjectId, sessionItem.UserId) //skip error

	annoProjectItem, err := data_anno_dao.AnnoProjectDao.Get(ctx, req.ProjectId, req.AnnoProjectId)
	if err != nil {
		return &data_anno_project_api.GetResponse{
			Code:   data_anno_project_api.GetResponse_CODE_NO_ANNO_PROJECT,
			ErrMsg: "标注项目不存在",
			Info:   emptyItem,
		}, nil
	}

	//生成结果
	info := annoProjectItem.ToAnnoProjectInfo()
	if err != nil {
		return nil, err
	}
	if memberItem != nil {
		info.MyTaskCount = memberItem.TaskCount
		info.MyDoneCount = memberItem.DoneCount
		info.IsMember = true
	}

	return &data_anno_project_api.GetResponse{
		Code: data_anno_project_api.GetResponse_CODE_OK,
		Info: info,
	}, nil
}
